package cn.lg.soar.activiti.service.impl;

import cn.lg.soar.activiti.dto.CommentDto;
import cn.lg.soar.activiti.dto.TaskDTO;
import cn.lg.soar.activiti.mapper.ActTaskMapper;
import cn.lg.soar.activiti.service.ActTaskService;
import cn.lg.soar.activiti.vo.HistoryTaskQO;
import cn.lg.soar.activiti.vo.HistoryTaskVO;
import cn.lg.soar.activiti.vo.TaskQO;
import cn.lg.soar.activiti.vo.TaskVO;
import cn.lg.soar.common.data.MapPlus;
import cn.lg.soar.common.data.MapPlusWrapper;
import cn.lg.soar.common.util.current.UserContext;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.*;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.activiti.image.ProcessDiagramGenerator;
import org.activiti.spring.ProcessEngineFactoryBean;

import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author luguoxiang
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
public class ActTaskServiceImpl implements ActTaskService {

	private final TaskService taskService;

	private final RuntimeService runtimeService;

	private final RepositoryService repositoryService;

	private final HistoryService historyService;

	private final ProcessEngineFactoryBean processEngine;
	private final ActTaskMapper mapper;

	public ActTaskServiceImpl(TaskService taskService, RuntimeService runtimeService, RepositoryService repositoryService, HistoryService historyService, ProcessEngineFactoryBean processEngine, ActTaskMapper mapper) {
		this.taskService = taskService;
		this.runtimeService = runtimeService;
		this.repositoryService = repositoryService;
		this.historyService = historyService;
		this.processEngine = processEngine;
		this.mapper = mapper;
	}

	@Override
	public IPage<TaskVO> todo(TaskQO qo, Collection<String> candidates) {
		Page<TaskVO> page = new Page<>(qo.getCurrent(), qo.getSize(), qo.getSearchCount());
		return mapper.todo(page, qo, candidates);
	}

	@Override
	public IPage<HistoryTaskVO> done(HistoryTaskQO qo) {
		Page<HistoryTaskVO> page = new Page<>(qo.getCurrent(), qo.getSize(), qo.getSearchCount());
		return mapper.done(page, qo);
	}

	@Override
	public IPage getTaskByName(Map<String, Object> params, String name) {
		MapPlus<String> mapPlus = new MapPlusWrapper<>(params);
		int page = mapPlus.getInteger("current");
		int limit = mapPlus.getInteger("size");

		TaskQuery taskQuery = taskService.createTaskQuery().taskCandidateOrAssigned(name)
				.taskTenantId(String.valueOf(UserContext.getUser().getCurrentTenantId()));

		IPage result = new Page(page, limit);
		result.setTotal(taskQuery.count());

		List<TaskDTO> taskDTOList = taskQuery.orderByTaskCreateTime().desc().listPage((page - 1) * limit, limit)
				.stream().map(task -> {
					TaskDTO dto = new TaskDTO();
					dto.setTaskId(task.getId());
					dto.setTaskName(task.getName());
					dto.setProcessInstanceId(task.getProcessInstanceId());
					dto.setNodeKey(task.getTaskDefinitionKey());
					dto.setCategory(task.getCategory());
					dto.setTime(task.getCreateTime());
					return dto;
				}).collect(Collectors.toList());
		result.setRecords(taskDTOList);
		return result;
	}

	@Override
	public List<CommentDto> getCommentByTaskId(String taskId) {
		// 使用当前的任务ID，查询当前流程对应的历史任务ID
		// 使用当前任务ID，获取当前任务对象
		Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
		// 获取流程实例ID
		List<CommentDto> commentDtoList = taskService.getProcessInstanceComments(task.getProcessInstanceId()).stream()
				.map(comment -> {
					CommentDto commentDto = new CommentDto();
					commentDto.setId(comment.getId());
					commentDto.setTime(comment.getTime());
					commentDto.setType(comment.getType());
					commentDto.setTaskId(comment.getTaskId());
					commentDto.setUserId(comment.getUserId());
					commentDto.setFullMessage(comment.getFullMessage());
					commentDto.setProcessInstanceId(comment.getProcessInstanceId());
					return commentDto;
				}).collect(Collectors.toList());
		return commentDtoList;
	}

	/**
	 * 追踪图片节点
	 * @param id
	 */
	@Override
	public InputStream viewByTaskId(String id) {
		// 使用当前任务ID，获取当前任务对象
		Task task = taskService.createTaskQuery().taskId(id).singleResult();

		String processInstanceId = task.getProcessInstanceId();
		ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
				.processInstanceId(processInstanceId).singleResult();
		HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
				.processInstanceId(processInstanceId).singleResult();
		String processDefinitionId = null;
		List<String> executedActivityIdList = new ArrayList<>();
		if (processInstance != null) {
			processDefinitionId = processInstance.getProcessDefinitionId();
			executedActivityIdList = this.runtimeService.getActiveActivityIds(processInstance.getId());
		}
		else if (historicProcessInstance != null) {
			processDefinitionId = historicProcessInstance.getProcessDefinitionId();
			executedActivityIdList = historyService.createHistoricActivityInstanceQuery()
					.processInstanceId(processInstanceId).orderByHistoricActivityInstanceId().asc().list().stream()
					.map(HistoricActivityInstance::getActivityId).collect(Collectors.toList());
		}

		BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
		ProcessEngineConfiguration processEngineConfiguration = processEngine.getProcessEngineConfiguration();
		Context.setProcessEngineConfiguration((ProcessEngineConfigurationImpl) processEngineConfiguration);
		ProcessDiagramGenerator diagramGenerator = processEngineConfiguration.getProcessDiagramGenerator();

		return diagramGenerator.generateDiagram(bpmnModel, "png", executedActivityIdList, Collections.emptyList(),
				processEngine.getProcessEngineConfiguration().getActivityFontName(),
				processEngine.getProcessEngineConfiguration().getLabelFontName(), "宋体", null, 1.0);

	}

	/**
	 * 批量删除
	 * @param ids
	 */
	@Override
	public void delTasks(String[] ids) {
		for (String taskId : ids) {
			Task task = taskService.createTaskQuery().taskId(taskId).singleResult();

			runtimeService.suspendProcessInstanceById(task.getProcessInstanceId());
			runtimeService.deleteProcessInstance(task.getProcessInstanceId(), "Deleted");
		}
	}

	@Override
	public List list(TaskDTO taskDTO) {
		TaskQuery taskQuery = taskService.createTaskQuery();
		List<TaskDTO> taskDTOList = taskQuery.orderByTaskCreateTime().desc().list().stream().map(task -> {
			TaskDTO dto = new TaskDTO();
			dto.setTaskId(task.getId());
			dto.setTaskName(task.getName());
			dto.setProcessInstanceId(task.getProcessInstanceId());
			dto.setNodeKey(task.getTaskDefinitionKey());
			dto.setCategory(task.getCategory());
			dto.setTime(task.getCreateTime());
			return dto;
		}).collect(Collectors.toList());
		return taskDTOList;
	}

}
